home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / compiler / Synchk.sml < prev    next >
Encoding:
Text File  |  1997-08-18  |  10.8 KB  |  375 lines  |  [TEXT/R*ch]

  1.  
  2. open List Fnlib Mixture Const Globals Location Units Asynt Asyntfn
  3.  
  4. (* --- Syntactic restrictions --- *)
  5.  
  6. fun inIds (ii : IdInfo) (iis : IdInfo list) =
  7.   exists (fn ii' => #id(#qualid ii) = #id(#qualid ii')) iis
  8. ;
  9.  
  10. fun checkDuplIds (iis : IdInfo list) msg =
  11.   case iis of
  12.       [] => ()
  13.     | ii :: iis' =>
  14.         if inIds ii iis' then
  15.           errorMsg (#idLoc (#info ii)) msg
  16.         else checkDuplIds iis' msg
  17. ;
  18.  
  19. fun checkAllIdsIn xs ys msg =
  20.   app (fn ii => if inIds ii ys then () else errorMsg (#idLoc (#info ii)) msg)
  21.       xs
  22. ;
  23.  
  24. fun checkTy (loc, ty') =
  25.   case ty' of
  26.     TYVARty _ => ()
  27.   | RECty fs =>
  28.       (app_field checkTy fs;
  29.        if duplicates (map fst fs) then
  30.          errorMsg loc "The same label is bound twice in a record type"
  31.        else ())
  32.   | CONty(tys, _) =>
  33.       app checkTy tys
  34.   | FNty(ty, ty') =>
  35.       (checkTy ty; checkTy ty')
  36. ;
  37.  
  38. fun checkAsPatSource (loc, pat') =
  39.   case pat' of
  40.     VARpat _ => ()
  41.   | TYPEDpat((_, VARpat _), _) => ()
  42.   | _ => errorMsg loc "Ill-formed source of a layered pattern"
  43. ;
  44.  
  45. fun checkPat (loc, pat') =
  46.   case pat' of
  47.     SCONpat _ => ()
  48.   | VARpat _ => ()
  49.   | WILDCARDpat => ()
  50.   | NILpat _ => ()
  51.   | CONSpat(_, p) => checkPat p
  52.   | EXNILpat _ => ()
  53.   | EXCONSpat(_, p) => checkPat p
  54.   | EXNAMEpat _ => fatalError "checkPat"
  55.   | REFpat p => checkPat p
  56.   | RECpat(ref (RECrp(fs, _))) =>
  57.       (app_field checkPat fs;
  58.        if duplicates (map fst fs) then
  59.          errorMsg loc "The same label is bound twice in a record pattern"
  60.        else ())
  61.   | RECpat(ref (TUPLErp _)) => fatalError "checkPat"
  62.   | VECpat ps => app checkPat ps
  63.   | PARpat p => checkPat p
  64.   | INFIXpat _ => fatalError "checkPat"
  65.   | TYPEDpat(pat, ty) => (checkPat pat; checkTy ty)
  66.   | LAYEREDpat(pat1, pat2) =>
  67.       (checkAsPatSource pat1;
  68.        checkPat pat1; checkPat pat2)
  69. ;
  70.  
  71. fun isFnExp (_, exp') =
  72.   case exp' of
  73.     PARexp exp => isFnExp exp
  74.   | TYPEDexp(exp, ty) => isFnExp exp
  75.   | FNexp _ => true
  76.   | _ => false
  77. ;
  78.  
  79. fun checkFnExp exp =
  80.   if isFnExp exp then () else
  81.   errorMsg (xLR exp) "Non-functional rhs expression in val rec declaration"
  82. ;
  83.  
  84. fun tyconsOfTBs tbs = map (fn(_, tycon, _) => tycon) tbs;
  85. fun tyconsOfTDs tds = map (fn(_, tycon) => tycon) tds;
  86. fun tyconsOfDBs dbs = map (fn(_, tycon, _) => tycon) dbs;
  87. fun consOfDBs dbs =
  88.   concat( map (fn(_, _, cbs) => map (fn ConBind(ii,_) => ii) cbs) dbs );
  89.  
  90. fun consOfEBs ebs =
  91.   map (fn EXDECexbind(ii,_) => ii
  92.         | EXEQUALexbind(ii,_) => ii)
  93.       ebs
  94. ;
  95.  
  96. fun appOpt f u (SOME x) = f x
  97.   | appOpt f u NONE     = u
  98. ;
  99.  
  100. fun checkTypBind (tyvars, tycon, ty) =
  101. (
  102.   checkTy ty;
  103.   checkDuplIds tyvars
  104.     "Duplicate parameter in a type binding";
  105.   checkAllIdsIn (varsOfTy ty) tyvars
  106.     "Unbound parameter in the rhs of a type binding"
  107. );
  108.  
  109. fun checkTypDesc (tyvars, tycon) =
  110.   checkDuplIds tyvars
  111.     "Duplicate parameter in a prim_type binding"
  112. ;
  113.  
  114. (* true, false, it, nil, ::, and ref may not be rebound or respecified
  115.    as constructors : *)
  116.  
  117. fun illegalCon id =
  118.     id = "true" orelse id = "false" orelse id = "it"
  119.     orelse id = "nil" orelse id = "::" orelse id = "ref"
  120.  
  121. fun initialUpper id =
  122.     let val char1 = CharVector.sub(id, 0)
  123.             handle Subscript => fatalError "initialUpper" 
  124.     in
  125.     if #"A" <= char1 andalso char1 <= #"Z" then () (* OK *)
  126.     else () (* warning *)
  127.     end;
  128.  
  129. fun checkConName ({qualid={id, ...}, info = {idLoc, ...}} : IdInfo) =
  130.     if illegalCon id then
  131.     errorMsg idLoc "Illegal rebinding or respecification"
  132.     else
  133.     ();
  134.  
  135. fun checkDatBind (tyvars, tycon, cbs) =
  136. (
  137.   app (fn ConBind(ii, SOME ty) =>
  138.                 (checkConName ii;
  139.          checkTy ty;
  140.                  checkAllIdsIn (varsOfTy ty) tyvars
  141.                    "Unbound parameter in the rhs of a datatype binding")
  142.         | ConBind(ii, NONE) => checkConName ii)
  143.           cbs;
  144.   checkDuplIds tyvars
  145.     "Duplicate parameter in a datatype binding"
  146. );
  147.  
  148. fun checkExBind (EXDECexbind(ii, ty_opt)) = 
  149.     (checkConName ii; appOpt checkTy () ty_opt)
  150.   | checkExBind (EXEQUALexbind(ii, _)) = checkConName ii;
  151. ;
  152.  
  153. fun checkInfixIds loc ids =
  154.   if duplicates ids then
  155.     errorMsg loc "An identifier appears twice in a fixity declaration"
  156.   else ()
  157. ;
  158.  
  159. fun patOfValBind (ValBind(pat, _)) = pat;
  160.  
  161. fun checkExp (loc, exp') =
  162.   case exp' of
  163.     SCONexp _ => ()
  164.   | VARexp _ => ()
  165.   | FNexp mrules =>
  166.       app checkMRule mrules
  167.   | APPexp(func, arg) =>
  168.       (checkExp func; checkExp arg)
  169.   | LETexp(dec, scope) =>
  170.       (checkDec false dec; checkExp scope)
  171.   | RECexp(ref (RECre fs)) =>
  172.       (app_field checkExp fs;
  173.        if duplicates (map fst fs) then
  174.          errorMsg loc "The same label is bound twice in a record expression"
  175.        else ())
  176.   | RECexp(ref (TUPLEre _)) => fatalError "checkExp"
  177.   | VECexp es =>
  178.       app checkExp es
  179.   | PARexp e => checkExp e
  180.   | INFIXexp _ => fatalError "checkExp"
  181.   | TYPEDexp(e, ty) =>
  182.       (checkExp e; checkTy ty)
  183.   | ANDALSOexp(e1, e2) =>
  184.       (checkExp e1; checkExp e2)
  185.   | ORELSEexp(e1, e2) =>
  186.       (checkExp e1; checkExp e2)
  187.   | HANDLEexp(e, mrules) =>
  188.       (checkExp e;
  189.        app checkMRule mrules)
  190.   | RAISEexp e =>
  191.       checkExp e
  192.   | IFexp(e0, e1, e2) =>
  193.       (checkExp e0; checkExp e1; checkExp e2)
  194.   | WHILEexp(e1, e2) =>
  195.       (checkExp e1; checkExp e2)
  196.   | SEQexp(e1, e2) =>
  197.       (checkExp e1; checkExp e2)
  198.  
  199. and checkMRule (MRule(pats, exp)) =
  200. (
  201.   app checkPat pats; checkExp exp;
  202.   checkDuplIds (foldR varsOfPatAcc [] pats)
  203.     "The same pattern variable is bound twice"
  204. )
  205.  
  206. and checkValBind (ValBind(pat, exp)) =
  207. (
  208.   checkPat pat; checkExp exp;
  209.   checkDuplIds (varsOfPatAcc pat [])
  210.     "The same variable is bound twice in a pattern"
  211. )
  212.  
  213. and checkPrimValBind (_, ty, _, _) =
  214.   checkTy ty
  215.  
  216. and checkDec onTop (loc, dec') =
  217.   case dec' of
  218.     VALdec (tyvars, (pvbs, rvbs)) =>
  219.       (app checkValBind pvbs;
  220.        app checkValBind rvbs;
  221.        checkDuplIds tyvars "Duplicate explicit type variable";
  222.        app (fn ValBind(_, exp) => checkFnExp exp) rvbs;
  223.        let val pat_vars =
  224.          foldR_map varsOfPatAcc patOfValBind
  225.            (foldR_map varsOfPatAcc patOfValBind [] rvbs) pvbs
  226.        in
  227.          checkDuplIds(pat_vars)
  228.             "The same variable is bound twice in a valbind"
  229.        end)
  230.   | PRIM_VALdec pbs =>
  231.       let val ()  = app checkPrimValBind pbs
  232.           val iis = map (fn (ii,_,_,_) => ii) pbs
  233.       in
  234.         checkDuplIds iis
  235.           "The same variable is bound twice in a prim_valbind"
  236.       end
  237.   | FUNdec _ => fatalError "checkDec"
  238.   | TYPEdec tbs =>
  239.       (app checkTypBind tbs;
  240.        let val tycons = tyconsOfTBs tbs in
  241.          checkDuplIds tycons
  242.            "The same tycon is bound twice in a type declaration"
  243.        end)
  244.   | PRIM_TYPEdec(_, tds) =>
  245.       (app checkTypDesc tds;
  246.        let val tycons = tyconsOfTDs tds in
  247.          checkDuplIds tycons
  248.            "The same tycon is bound twice in a prim_type declaration"
  249.        end)
  250.   | DATATYPEdec(dbs, tbs_opt) =>
  251.       (app checkDatBind dbs;
  252.        appOpt (app checkTypBind) () tbs_opt;
  253.        let val tycons = tyconsOfDBs dbs @ appOpt tyconsOfTBs [] tbs_opt
  254.            val cons = consOfDBs dbs
  255.        in
  256.          checkDuplIds tycons
  257.            "The same tycon is bound twice in a datatype declaration";
  258.          checkDuplIds cons
  259.            "The same con is bound twice in a datatype declaration"
  260.        end)
  261.   | ABSTYPEdec(dbs, tbs_opt, dec2) =>
  262.       (app checkDatBind dbs;
  263.        appOpt (app checkTypBind) () tbs_opt;
  264.        let val tycons = tyconsOfDBs dbs @ appOpt tyconsOfTBs [] tbs_opt
  265.            val cons = consOfDBs dbs
  266.        in
  267.          checkDuplIds tycons
  268.            "The same tycon is bound twice in an abstype declaration";
  269.          checkDuplIds cons
  270.            "The same con is bound twice in an abstype declaration";
  271.          checkDec onTop dec2
  272.        end)
  273.   | EXCEPTIONdec ebs =>
  274.       (app checkExBind ebs;
  275.        checkDuplIds (consOfEBs ebs)
  276.          "The same excon is bound twice in an exception declaration")
  277.   | LOCALdec (dec1, dec2) =>
  278.       (checkDec false dec1; checkDec onTop dec2)
  279.   | OPENdec _ =>
  280.       (*
  281.       if not(!hasSpecifiedSignature) andalso
  282.          onTop & currentUnitName() <> "Top"
  283.       then
  284.         (msgIBlock 0;
  285.          errLocation loc;
  286.          errPrompt "`open' is not permitted at the top level,";
  287.          msgEOL();
  288.          errPrompt "unless the unit has explicitly specified signature";
  289.          msgEOL();
  290.          msgEBlock();
  291.          raise Toplevel); *)
  292.       ()
  293.   | EMPTYdec => ()
  294.   | SEQdec (dec1, dec2) =>
  295.       (checkDec onTop dec1; checkDec onTop dec2)
  296.   | FIXITYdec(_, ids) =>
  297.       checkInfixIds loc ids
  298. ;
  299.  
  300. (* --- Signatures --- *)
  301.  
  302. fun checkExDesc (ii, ty_opt) = 
  303.     (checkConName ii; appOpt checkTy () ty_opt);
  304.  
  305. fun consOfEDs eds =
  306.   map (fn (ii,_) => ii) eds
  307. ;
  308.  
  309. fun checkSpec onTop (loc, spec') =
  310.   case spec' of
  311.     VALspec vds =>
  312.       (if not onTop then errorMsg loc
  313.          "Value specifications are permitted only at the top level"
  314.        else ();
  315.        app (fn(_, ty) => checkTy ty) vds;
  316.        let val iis = map (fn(ii,_) => ii) vds in
  317.          checkDuplIds iis
  318.            "The same variable is bound twice in a value description"
  319.        end)
  320.   | PRIM_VALspec pbs =>
  321.       (if not onTop then errorMsg loc
  322.          "Primitive value specifications are permitted only at the top level"
  323.        else ();
  324.        app checkPrimValBind pbs;
  325.        let val iis = map (fn(ii,_,_,_) => ii) pbs in
  326.          checkDuplIds iis
  327.            "The same variable is bound twice in a prim_valbind"
  328.        end)
  329.   | TYPEDESCspec(_, tds) =>
  330.       (if not onTop then errorMsg loc
  331.          "Abstract type specifications are permitted only at the top level"
  332.        else ();
  333.        app checkTypDesc tds;
  334.        let val tycons = tyconsOfTDs tds in
  335.          checkDuplIds tycons
  336.            "The same tycon is bound twice in a type description"
  337.        end)
  338.   | TYPEspec tbs =>
  339.       (app checkTypBind tbs;
  340.        let val tycons = tyconsOfTBs tbs in
  341.          checkDuplIds tycons
  342.            "The same tycon is bound twice in a manifest type description"
  343.        end)
  344.   | DATATYPEspec(dbs, tbs_opt) =>
  345.       (if not onTop then errorMsg loc
  346.          "Variant type specifications are permitted only at the top level"
  347.        else ();
  348.        app checkDatBind dbs;
  349.        appOpt (app checkTypBind) () tbs_opt;
  350.        let val tycons = tyconsOfDBs dbs @ appOpt tyconsOfTBs [] tbs_opt
  351.            val cons = consOfDBs dbs
  352.        in
  353.          checkDuplIds tycons
  354.            "The same tycon is bound twice in a datatype description";
  355.          checkDuplIds cons
  356.            "The same con is bound twice in a datatype description"
  357.        end)
  358.   | EXCEPTIONspec eds =>
  359.       (if not onTop then errorMsg loc
  360.          "Exception specifications are permitted only at the top level"
  361.        else ();
  362.        app checkExDesc eds;
  363.        checkDuplIds (consOfEDs eds)
  364.          "The same excon is bound twice in an exception description")
  365.   | LOCALspec (spec1, spec2) =>
  366.       (checkSpec false spec1; checkSpec onTop spec2)
  367.   | OPENspec _ =>
  368.       if onTop then errorMsg loc
  369.         "`open' is not permitted at the top level"
  370.       else ()
  371.   | EMPTYspec => ()
  372.   | SEQspec (spec1, spec2) =>
  373.       (checkSpec onTop spec1; checkSpec onTop spec2)
  374. ;
  375.